package com.jinunn.system.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jinunn.system.common.constant.SystemConstants;
import com.jinunn.system.converter.UserConverter;
import com.jinunn.system.entity.User;
import com.jinunn.system.exception.BusinessException;
import com.jinunn.system.mapper.UserMapper;
import com.jinunn.system.model.dto.UserAuthInfoDto;
import com.jinunn.system.model.params.UpdatePwdParam;
import com.jinunn.system.model.params.UpdateUserStatusParam;
import com.jinunn.system.model.params.UserParam;
import com.jinunn.system.model.vo.user.UserDetailVo;
import com.jinunn.system.model.vo.user.UserInfoVO;
import com.jinunn.system.model.vo.user.UserPageQuery;
import com.jinunn.system.model.vo.user.UserPageVO;
import com.jinunn.system.secutity.service.PermissionService;
import com.jinunn.system.secutity.utils.SecurityUtils;
import com.jinunn.system.service.RoleMenuService;
import com.jinunn.system.service.RoleService;
import com.jinunn.system.service.UserRoleService;
import com.jinunn.system.service.UserService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Objects;
import java.util.Set;

/**
 * <p>
 * 用户信息表 服务实现类
 * </p>
 *
 * @author JIN
 * @since 2024-07-10
 */
@Slf4j
@Service
@RequiredArgsConstructor(onConstructor_ = @Autowired)
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    private final UserConverter userConverter;
    private final PasswordEncoder passwordEncoder;
    private final RoleMenuService roleMenuService;
    private final RoleService roleService;
    private final PermissionService permissionService;
    private final UserRoleService userRoleService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean saveUser(UserParam userParam) {
        String username = userParam.getUsername();
        Long count = this.lambdaQuery().eq(User::getUsername, username).count();
        Assert.isTrue(count == 0, () -> new BusinessException("用户名已存在"));

        User entity = userConverter.convertToEntity(userParam);

        // 设置默认加密密码
        String defaultEncryptPwd = passwordEncoder.encode(SystemConstants.DEFAULT_PASSWORD);
        entity.setPassword(defaultEncryptPwd);
        boolean result = this.save(entity);
        if (result) {
            // 保存用户角色
            userRoleService.upsertUserRoles(entity.getId(), userParam.getRoleIds());
        }
        return result;
    }

    @Override
    public UserAuthInfoDto getUserAuthInfo(String username) {
        UserAuthInfoDto authInfoDto = baseMapper.getUserAuthInfo(username);
        if (Objects.nonNull(authInfoDto)) {
            Set<String> roles = authInfoDto.getRoles();
            if (CollectionUtil.isNotEmpty(roles)) {
                // 查询角色对应的权限标识
                Set<String> perms = roleMenuService.getRolePermsByRoleCodes(roles);
                authInfoDto.setPerms(perms);
            }
            // 获取最大范围的数据权限
            Integer dataScope = roleService.getMaximumDataScope(roles);
            authInfoDto.setDataScope(dataScope);
        }
        return authInfoDto;
    }

    @Override
    public UserInfoVO getCurrentUserInfo() {
        String username = SecurityUtils.getUsername();
        // 查询用户信息
        User user = this.lambdaQuery()
                .select(User::getId, User::getUsername, User::getNickname, User::getAvatar)
                .eq(User::getUsername, username).one();
        // entity -> VO
        UserInfoVO userInfoVO = userConverter.toUserInfoVo(user);
        // 用户角色集合
        Set<String> roles = SecurityUtils.getRoles();
        userInfoVO.setRoles(roles);
        // 用户权限集合
        if (CollectionUtil.isNotEmpty(roles)) {
            Set<String> perms = permissionService.getRolePermsFormCache(roles);
            userInfoVO.setPerms(perms);
        }
        return userInfoVO;
    }

    @Override
    public boolean updatePassword(UpdatePwdParam param) {
        return this.update(new LambdaUpdateWrapper<User>()
                .eq(User::getId, param.getUserId())
                .set(User::getPassword, passwordEncoder.encode(param.getPassword()))
        );
    }

    @Override
    public boolean updateUserStatus(UpdateUserStatusParam param) {
        return this.update(new LambdaUpdateWrapper<User>()
                .eq(User::getId, param.getUserId())
                .set(User::getStatus, param.getStatus()));
    }

    @Override
    public boolean deleteUser(String id) {
        Assert.isTrue(StrUtil.isNotBlank(id), () -> new BusinessException("删除的用户数据为空"));
        return this.removeById(id);
    }

    @Override
    public UserDetailVo getUserDetail(Long userId) {
        return this.baseMapper.getUserDetail(userId);
    }


    @Override
    public IPage<UserPageVO> listPagedUsers(UserPageQuery queryParams) {
        return this.baseMapper.getPage(queryParams.toPage(), queryParams);
    }
}
